// 05_ownership_and_borrowing.rs
// 演示 Rust 中的所有权和借用概念

// 将原来的 main 函数改为公共的 run 函数
pub fn run() {
    // 1. 所有权的基本规则
    // a. Rust 中的每个值都有一个所有者
    // b. 值在任一时刻只能有一个所有者
    // c. 当所有者离开作用域时，值将被丢弃
    
    // 2. 字符串示例（String 是一个拥有所有权的类型）
    let s1 = String::from("hello"); // s1 是字符串 "hello" 的所有者
    println!("s1: {}", s1);
    
    // 3. 移动（Move）语义
    // 将 s1 的所有权转移给 s2
    let s2 = s1;
    println!("s2: {}", s2);
    
    // 此时 s1 不再有效，尝试使用 s1 将导致编译错误
    // println!("s1: {}", s1); // 取消注释这行会导致编译错误
    
    // 4. 复制（Copy）语义
    // 对于基本类型（如整数、布尔值等），它们实现了 Copy trait
    let x = 5;
    let y = x; // x 的值被复制给 y，x 仍然有效
    println!("x: {}, y: {}", x, y);
    
    // 5. 克隆（Clone）
    // 对于没有实现 Copy trait 的类型，可以使用 clone 方法显式复制数据
    let s3 = String::from("world");
    let s4 = s3.clone(); // 深度复制，s3 仍然有效
    println!("s3: {}, s4: {}", s3, s4);
    
    // 6. 函数调用中的所有权
    let s5 = String::from("函数调用");
    take_ownership(s5); // s5 的所有权被转移到函数中
    
    // s5 现在不再有效
    // println!("s5: {}", s5); // 取消注释这行会导致编译错误
    
    let num = 10;
    makes_copy(num); // num 实现了 Copy，仍然有效
    println!("num 仍然有效: {}", num);
    
    // 7. 返回值中的所有权
    let s6 = give_ownership(); // s6 获取返回值的所有权
    println!("s6: {}", s6);
    
    let s7 = String::from("转移并返回");
    let s8 = take_and_give_back(s7); // s7 转移到函数，然后函数返回所有权给 s8
    println!("s8: {}", s8);
    
    // 8. 借用（Borrowing）
    // 可以通过引用（&）来借用值而不获取所有权
    let s9 = String::from("借用示例");
    let len = calculate_length(&s9); // 传递引用，不获取所有权
    println!("字符串 '{}' 的长度是 {}", s9, len);
    
    // 9. 可变引用
    let mut s10 = String::from("可变引用");
    change_string(&mut s10); // 传递可变引用
    println!("修改后的字符串: {}", s10);
    
    // 可变引用的限制：同一作用域内，对同一数据只能有一个可变引用
    let mut s11 = String::from("限制");
    let r1 = &mut s11;
    // let r2 = &mut s11; // 取消注释这行会导致编译错误
    println!("r1: {}", r1);
    
    // 但可以在不同的作用域中拥有多个可变引用
    { 
        let r2 = &mut s11;
        println!("r2: {}", r2);
    } // r2 离开作用域，不再有效
    
    let r3 = &mut s11;
    println!("r3: {}", r3);
    
    // 10. 不可变引用和可变引用不能同时存在
    let s12 = String::from("同时引用");
    let r4 = &s12; // 不可变引用
    let r5 = &s12; // 可以有多个不可变引用
    println!("r4: {}, r5: {}", r4, r5);
    // let r6 = &mut s12; // 取消注释这行会导致编译错误
    
    // 当不可变引用离开作用域后，可以创建可变引用
    { 
        let r6 = &s12;
        println!("r6: {}", r6);
    } // r6 离开作用域
    
    let r7 = &mut s12;
    println!("r7: {}", r7);
} // 所有变量离开作用域，相应的内存被自动释放

// 函数获取字符串的所有权
fn take_ownership(some_string: String) {
    println!("函数内部获取的字符串: {}", some_string);
} // some_string 离开作用域，内存被释放

// 函数使用实现了 Copy 的类型
fn makes_copy(some_integer: i32) {
    println!("函数内部获取的整数: {}", some_integer);
} // some_integer 离开作用域，但因为实现了 Copy，不会有特殊操作

// 函数返回一个字符串的所有权
fn give_ownership() -> String {
    let some_string = String::from("返回的字符串");
    some_string // 返回 some_string，所有权被转移
} // 如果 some_string 没有被返回，它会在这里被释放

// 函数接收并返回一个字符串的所有权
fn take_and_give_back(a_string: String) -> String {
    a_string // 返回 a_string，所有权被转移
} // 如果 a_string 没有被返回，它会在这里被释放

// 函数借用一个字符串（使用不可变引用）
fn calculate_length(s: &String) -> usize {
    s.len() // 返回字符串长度，不获取所有权
} // s 离开作用域，但因为它是引用而不是所有者，所以不会释放内存

// 函数借用一个可变字符串（使用可变引用）
fn change_string(s: &mut String) {
    s.push_str(", 已修改"); // 修改借用的字符串
} // s 离开作用域，但因为它是引用而不是所有者，所以不会释放内存